/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 adventure_object.h

	$Header: /game/adventure_object.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( ADVENTURE_OBJECT_H_INCLUDED )
#define ADVENTURE_OBJECT_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// kill "inherits via dominance" warning.  It's informational only, it's going to happen
// with anything derived from t_abstract_adv_object, and it prevents setting
// "treat warnings as errors".
#pragma warning( disable: 4250 )
#pragma warning( disable: 4786 )

#include <vector>
#include "adv_map_point.h"
#include "adv_object_map_info.h"
#include "adventure_object_global_id.h"
#include "adventure_object_memory_cache.h"
#include "abstract_adv_object.h"
#include "counted_ptr.h"
#include "handler.h"
#include "path_point_array.h"
#include "skill.h"

enum	t_adv_object_icon_type;
class	t_adventure_ai;
class	t_adventure_frame;
class	t_adventure_map;
class	t_adventure_map_window;
class	t_adventure_path;
class	t_adventure_path_finder;
struct	t_adventure_path_point;
class	t_army;
struct	t_bitmap_cursor;
enum	t_combat_result;
class	t_creature_array;
enum	t_direction;
struct	t_level_map_point_2d;
struct	t_map_rect_2d;
class	t_map_renderer;

template < typename t_val >
class  t_map_segment_overlay;

struct	t_mouse_event;
enum	t_path_search_type;
class	t_player;
class	t_progress_handler;
enum	t_spell;
enum	t_tile_visibility;

template <typename t_key_arg,
		typename t_key_compare_arg = std::less< t_key_arg >,
		typename t_allocator_arg = std::allocator< t_key_arg > >
class  t_vector_set;

class  t_window;

// -------------------------------------------------------------------
// t_tile_visibility_data - used to represent a tile's visibility data
// of an adventure object
// -------------------------------------------------------------------

class t_tile_visibility_data
{
public:
	// Constructors
	t_tile_visibility_data( bool visible = false );
	explicit t_tile_visibility_data( t_skill_mastery scouting );

	// Member functions
	t_skill_mastery	get_anti_stealth() const;
	bool			is_visible() const;

private:
	t_skill_mastery	m_anti_stealth;
	bool			m_visible;
};

inline t_tile_visibility_data::t_tile_visibility_data( bool visible )
	:	m_anti_stealth( k_mastery_none ),
		m_visible( visible )
{
}

inline t_tile_visibility_data::t_tile_visibility_data( t_skill_mastery scouting )
	:	m_anti_stealth( scouting ),
		m_visible( true )
{
}

inline t_skill_mastery t_tile_visibility_data::get_anti_stealth() const
{
	return m_anti_stealth;
}

inline bool t_tile_visibility_data::is_visible() const
{
	return m_visible;
}

// -------------------------------------------------------------------
// class to represent adventure objects (from trees to castles)
// -------------------------------------------------------------------
class t_adventure_object : public virtual t_abstract_adv_object, public virtual t_adv_object_map_info, public t_counted_object,
 public t_adventure_object_memory_cache_refrence
{
public:
	// Types
	typedef t_adv_object_icon_type								t_icon_type;
	typedef t_vector_set< t_map_point_2d >						t_tile_point_set;
	typedef t_map_segment_overlay< t_tile_visibility_data >		t_visibility_overlay;
	
	// Found point, filter out boolean
	typedef t_handler_2< t_adv_map_point const &, bool & >		t_find_space_filter_handler;
	
	// Found point, trigger cell point, stop scan boolean
	typedef t_handler_3< t_adv_map_point const &, t_adv_map_point const &, bool & >	t_scan_adjacent_space_handler;

	t_adventure_object();
	virtual ~t_adventure_object();

	virtual std::string		get_name() const = 0;
	virtual std::string		get_balloon_help() const;

	virtual void			activate_trigger( t_army* army, t_adv_map_point const& point, 
		                                   t_direction direction, t_adventure_frame* frame );
	virtual float			ai_value( t_adventure_ai const& ai, t_creature_array const& army, int move_cost ) const;	
	virtual float			ai_activation_value_drop( t_creature_array const& army ) const;
	virtual bool			blocks_army( t_creature_array const&			army,
										 t_path_search_type		path_type ) const;
	virtual t_clone_ptr		clone() const;
	virtual void			destroy();
	bool					find_adjacent_space( t_adv_map_point & result,
												 t_creature_array const& army,
												 t_find_space_filter_handler handler = t_find_space_filter_handler()) const;
	bool					find_adjacent_space( t_adv_map_point & result,
												 t_creature_array const& army,
												 bool find_ocean_space,
												 t_find_space_filter_handler handler = t_find_space_filter_handler()) const;
	bool					find_nearby_space( t_adv_map_point & result, t_creature_array const& army ) const;
	virtual t_bitmap_cursor const& get_cursor( t_adventure_map_window const& window,
		                                     t_army const* army ) const;
	void					float_object();
	virtual t_adventure_ai const* get_ai() const;
	t_adventure_object*		get_adventure_object();
	virtual t_skill_mastery	get_anti_stealth_level() const;
	virtual int				get_attack_range() const;
	t_adventure_global_id	get_global_id() const;
	virtual t_icon_type		get_icon_type() const;
	t_skill_mastery			get_information_level() const; // get information given to local player
														   // by scouting level.
	t_adventure_map*		get_map() const;
	t_adventure_map_window* get_map_window() const;
	t_adventure_frame*		get_adventure_frame() const;
	int						get_map_id() const;
	virtual t_adv_map_point	get_position() const;
	virtual int				get_scouting_range() const;
	bool					get_trigger_cell( t_adv_map_point & result ) const;
	virtual int				get_version() const;
	bool					hidden_by_fog_of_war( int team_num ) const;
	bool					hidden_by_shroud( int team_num ) const;
	virtual void			initialize( t_adventure_map& map );
	virtual bool			is_bridge() const;
	virtual bool			is_event_recordable() const;
	bool					is_floating() const;
	bool					is_on_map() const;
	virtual bool			is_ramp() const;
	virtual bool			is_removable() const;
	virtual bool			is_triggered_by( t_creature_array const& army ) const;
	bool					is_under_fog_of_war( int team_num ) const;
	bool					is_under_shroud( int team_num ) const;
	virtual void			left_double_click( t_mouse_event const& event, 
							                   t_adventure_frame* adventure_frame );
	void					mark_visibility(
								int						level,
								t_visibility_overlay &	visibility_overlay ) const;
	void					move( t_adv_map_point const& point );
	virtual void			on_adventure_map_destruction();
	virtual void			on_begin_turn();
	virtual void			on_combat_end( t_army* attacker, t_combat_result result,
										   t_creature_array* losses, 
										   t_adventure_frame* adventure_frame );
	virtual void			on_end_turn();
	void					on_move_begin();
	void					on_move_end();
	virtual void			on_removed();
	virtual void			pathing_destination_query( t_adventure_path_point const& source, 
													   t_adventure_path_finder & path_finder ) const;
	virtual void			place( t_adventure_map& map, t_adv_map_point const& point );
	virtual bool            preplacement( t_adventure_map& map, int pass );
	virtual void			preprocess_new_day();
	virtual void			process_new_day();
	virtual bool			process_timed_events( t_adventure_map& map, bool start_of_day = true);
	virtual bool			process_continuous_events( t_adventure_map& map );
	virtual bool			process_triggerable_events( t_adventure_map& map, std::string const& name );
	virtual void			read_postplacement( t_adventure_map& map ) {}
	virtual bool			read_from_map( std::streambuf& buffer, t_progress_handler* handler );
	virtual void			right_click( t_mouse_event const& event,
		                                 t_adventure_frame* adventure_frame );
	bool					scan_adjacent_spaces( t_scan_adjacent_space_handler scanner, t_adv_map_point & stopping_point ) const;
	virtual void			set_event_recordable(bool event_recordable);
	void					set_global_id ( t_adventure_global_id new_global_id );
	void					sink_object();
	virtual bool			trigger_event(t_army& army);
	virtual void			update_state();
	virtual bool			uses_bridge_heights() const;
	virtual bool			write_object( std::streambuf& buffer ) const = 0;

protected:
	
	bool					m_event_recordable;
	bool					m_floating;
	t_adventure_global_id	m_global_id;
	t_adventure_map*		m_map;
	int						m_map_id;				// id as it appears on the map
	t_adv_map_point			m_location;
	int						m_removal_count;

	void	on_owner_changed( int new_owner, int old_owner );
	void	on_scouting_range_changed( int new_range, int old_range );
};

inline float t_adventure_object::ai_value( t_adventure_ai const& ai, t_creature_array const& army, int move_cost ) const
{
	return 0.0f;
}

inline float t_adventure_object::ai_activation_value_drop( t_creature_array const& army ) const
{
	return 0.0f;
}

inline bool t_adventure_object::is_on_map() const
{
	return( m_map_id >= 0 );
}

inline int t_adventure_object::get_map_id() const
{
	return m_map_id;
}

inline t_adventure_global_id t_adventure_object::get_global_id() const
{
	return m_global_id;
}

inline t_adv_map_point t_adventure_object::get_position() const
{
	return m_location;
}

inline bool t_adventure_object::is_floating() const
{
	return m_floating;
}

inline void	t_adventure_object::set_global_id ( t_adventure_global_id new_global_id )
{	
	m_global_id = new_global_id;
	t_adventure_object_memory_cache_refrence::set_global_id_for_memory_cache( new_global_id );
}

#endif // ADVENTURE_OBJECT_H_INCLUDED
